package cn.yunyichina.provider.framework.dubbo.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.yunyichina.provider.framework.data.SpringContextHandler;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.framework.filter.CallDataFilter;
import cn.yunyichina.provider.framework.reflect.MethodReflect;
import cn.yunyichina.provider.framework.utils.ExceptionUtils;
import cn.yunyichina.provider.iface.entity.common.MethodArgs;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.iface.service.IService;
import cn.yunyichina.utils.convert.JsonUtils;

import com.alibaba.fastjson.JSON;

/**
 * 云医通标准通讯接口服务
 *
 * @author zhangkw
 */
public class YytServiceImpl implements IService {

    private static final Logger logger = LoggerFactory.getLogger(YytServiceImpl.class);

    public Response callFromExternal(Map<String, String> data) {
    	
    	logger.info("【外部调用】原始请求参数->"+JSON.toJSONString(data));
        Response response = new Response();
        try {
            /* 检测参数是否正常，并返回对应服务名，方法名，参数 */
            MethodArgs methodargs = CallDataFilter.filter(data, 1);
            if ("1".equals(methodargs.getResultCode())) {
                Object serviceObject = SpringContextHandler.getBean(methodargs.getServiceName());
                if (serviceObject == null) {
                    if (methodargs.getServiceSecondName() != null && !"".equals(methodargs.getServiceSecondName())) {
                        serviceObject = SpringContextHandler.getBean(methodargs.getServiceSecondName());
                        if (serviceObject == null) {
                            response.setResultCodeAndMessage("10",
                                    "找不到对应的服务" + methodargs.getServiceName() +
                                            "或服务" + methodargs.getServiceSecondName() + "的实现!");
                            return response;
                        }
                    }
                }

                logger.info("过滤参数后结果为->" + JSON.toJSONString(methodargs) + ",服务：" + serviceObject);

                /* 反射调用对应的服务实现 */
                String sessionId = data.containsKey("sessionid") ? data.get("sessionid") : "";
                String appId=data.containsKey("app_id")?data.get("app_id"):"";
                Object rep = MethodReflect.invokeMethodGernaral(
                        serviceObject, methodargs.getMethodName(),
                        new Object[]{methodargs.getMethodData(), sessionId,appId}
                );

                if (rep instanceof ResponseObject) {
                    ResponseObject robject = (ResponseObject) rep;
                    response.setResultCodeAndMessageAndResult(
                            robject.getResultCode(),
                            robject.getResultMessage(),
                            JsonUtils.toJsonString(robject.getResultObject())
                    );
                } else if (rep instanceof Response) {
                    response = (Response) rep;
                } else if (rep instanceof String) {
                    response.setResult((String) rep);
                } else {
                    response.setResult(JsonUtils.toJsonString(rep));
                }

                return response;
            } else {
                response.setResultCodeAndMessage(methodargs.getResultCode(), methodargs.getResultMessage());
            }
        } catch (CallException cex) {
            response.setResultCodeAndMessage(String.valueOf(cex.getResultCode()), cex.getMessage());
            logger.error(cex.getMessage());
        } catch (Exception e) {
            Throwable target;
            if (e.getCause() != null) {
                target = e.getCause();
            } else {
                target = e;
            }
            response.setResultCodeAndMessage(getErrorCode(), ExceptionUtils.getExceptionMessage(target));
            logger.error("[YytServiceImpl.callFromInternal]", e);
        }
        
        logger.info("【外部调用】返回->"+JSON.toJSONString(response));
        return response;
    }

    public Response callUnderlineFromInternal(String sessionId, String method, String data, short base64Flag) {
        return callFromInternal(sessionId, method, data, base64Flag, (short) 1);
    }

    public ResponseObject callUnderlineFromInternalObject(String sessionId, String method, String data, short base64Flag) {
        return callFromInternalObject(sessionId, method, data, base64Flag, (short) 1);
    }

    public Response callHumpFromInternal(String sessionId, String method, String data, short base64Flag) {
        return callFromInternal(sessionId, method, data, base64Flag, (short) 2);
    }

    /**
     * 统一内部调用处理方式
     *
     * @param sessionId
     * @param method
     * @param data
     * @param base64Flag 是否需要解密base64 0-不需要 1-需要解密
     * @param methodFlag 1-返回下划线 2-返回驼峰规则的数据
     * @return
     */
    private Response callFromInternal(String sessionId, String method, String data, short base64Flag, short methodFlag) {

    	logger.info("【内部调用1】原始请求参数->"+sessionId+","+method+","+data+","+base64Flag+","+methodFlag);
        Response response = new Response();
        Map<String, String> postdata = new HashMap<>();
        postdata.put("method", method);
        postdata.put("data", data);
        postdata.put("sessionid", sessionId == null ? "" : sessionId);
        try {
            /* 检测参数是否正常，并返回对应服务名，方法名，参数 */
            MethodArgs methodargs = CallDataFilter.filter(postdata, base64Flag);

            if ("1".equals(methodargs.getResultCode())) {
                Object serviceObject = SpringContextHandler.getBean(methodargs.getServiceName());
                if (serviceObject == null) {
                    if (methodargs.getServiceSecondName() != null && !"".equals(methodargs.getServiceSecondName())) {
                        serviceObject = SpringContextHandler.getBean(methodargs.getServiceSecondName());
                        if (serviceObject == null) {
                            response.setResultCodeAndMessage("10", "找不到对应的服务" + methodargs.getServiceName() + "或服务"
                                    + methodargs.getServiceSecondName() + "的实现!");
                            return response;
                        }
                    }
                }

                logger.info("【内部调用1】过滤参数后结果为->" + JSON.toJSONString(methodargs) + ",服务：" + serviceObject);
                
                /* 反射调用对应的服务实现 */
                Object rep = MethodReflect.invokeMethodGernaral(serviceObject, methodargs.getMethodName(),
                        new Object[]{methodargs.getMethodData(), sessionId});

                if (rep instanceof ResponseObject) {
                    ResponseObject robject = (ResponseObject) rep;
                    if (methodFlag == 1) {
                        response.setResultCodeAndMessageAndResult(robject.getResultCode(), robject.getResultMessage(),
                                JsonUtils.toJsonString(robject.getResultObject()));
                    } else {
                        response.setResultCodeAndMessageAndResult(robject.getResultCode(), robject.getResultMessage(),
                                JSON.toJSONString(robject.getResultObject()));
                    }
                } else if (rep instanceof Response) {
                    response = (Response) rep;
                } else if (rep instanceof String) {
                    response.setResult((String) rep);
                } else {
                    response.setResult(JsonUtils.toJsonString(rep));
                }

                return response;
            } else {
                response.setResultCodeAndMessage(methodargs.getResultCode(), methodargs.getResultMessage());
            }
        } catch (CallException cex) {
            response.setResultCodeAndMessage(String.valueOf(cex.getResultCode()), cex.getMessage());
            logger.error(cex.getMessage());
        } catch (Exception e) {
            Throwable target;
            if (e.getCause() != null) {
                target = e.getCause();
            } else {
                target = e;
            }
            response.setResultCodeAndMessage(getErrorCode(), ExceptionUtils.getExceptionMessage(target));
            logger.error("[YytServiceImpl.callFromInternal]", e);
        }
        logger.info("【内部调用1】返回->"+JSON.toJSONString(response));
        return response;
    }

    private ResponseObject callFromInternalObject(String sessionId, String method, String data, short base64Flag, short methodFlag) {
    	
    	logger.info("【内部调用2】原始请求参数->"+sessionId+","+method+","+data+","+base64Flag+","+methodFlag);
    	ResponseObject response = new ResponseObject();
        Map<String, String> postdata = new HashMap<>();
        postdata.put("method", method);
        postdata.put("data", data);
        postdata.put("sessionid", sessionId == null ? "" : sessionId);
        try {
            /* 检测参数是否正常，并返回对应服务名，方法名，参数 */
            MethodArgs methodargs = CallDataFilter.filter(postdata, base64Flag);
            if ("1".equals(methodargs.getResultCode())) {
                Object serviceObject = SpringContextHandler.getBean(methodargs.getServiceName());
                if (serviceObject == null) {
                    if (methodargs.getServiceSecondName() != null && !"".equals(methodargs.getServiceSecondName())) {
                        serviceObject = SpringContextHandler.getBean(methodargs.getServiceSecondName());
                        if (serviceObject == null) {
                            response.setResultCodeAndMessage("10", "找不到对应的服务" + methodargs.getServiceName() + "或服务"
                                    + methodargs.getServiceSecondName() + "的实现!");
                            return response;
                        }
                    }
                }
                
                logger.info("【内部调用2】过滤参数后结果为->" + JSON.toJSONString(methodargs) + ",服务：" + serviceObject);

                /* 反射调用对应的服务实现 */
                Object rep = MethodReflect.invokeMethodGernaral(serviceObject, methodargs.getMethodName(),
                        new Object[]{methodargs.getMethodData(), sessionId});

                if (rep instanceof ResponseObject) {
                    ResponseObject robject = (ResponseObject) rep;
                    if (methodFlag == 1) {
                        response.setResultCodeAndMessageAndResult(robject.getResultCode(), robject.getResultMessage(), robject.getResultObject());
                    } else {
                        response.setResultCodeAndMessageAndResult(robject.getResultCode(), robject.getResultMessage(),
                                JSON.toJSONString(robject.getResultObject()));
                    }
                } else if (rep instanceof String) {
                    response.setResultObject(rep);
                } else {
                    response.setResultObject(JsonUtils.toJsonString(rep));
                }
                return response;
            } else {
                response.setResultCodeAndMessage(methodargs.getResultCode(), methodargs.getResultMessage());
            }
        } catch (CallException cex) {
            response.setResultCodeAndMessage(String.valueOf(cex.getResultCode()), cex.getMessage());
            logger.error(cex.getMessage());
        } catch (Exception e) {
            response.setResultCodeAndMessage(getErrorCode(), ExceptionUtils.getExceptionMessage(e));
            logger.error("[YytServiceImpl.callFromInternalObject]", e);
        }
        
        logger.info("【内部调用2】返回->"+JSON.toJSONString(response));
        return response;
    }

    public String getErrorCode() {
        return "2";
    }

}
